/**
 * 
 */
package com.curluin.inputInterpretation;

import java.util.Vector;

import com.curluin.math.MyVector;

/**
 * Represents a touch event starting with a point of first contact with the screen
 * followed by a wipe with a certain trajectory and finished by a point of break of contact
 * @author alex
 *
 */
public class TouchEvent {
	
	public static final int TOUCH_STARTED = 1;
	public static final int TOUCH_MOVING = 2;
	public static final int TOUCH_FINISHED = 3;
	
	/**
	 * Min Distance (percentage of screenwidth) which must be fullfilled for @link{com.curluin.inputInterpretation.TouchEvent.actuallyMoved()}
	 */
	private static float minDist=0.003f;
	/**
	 * Point of first contact
	 */
	public TouchPoint downPoint;
	
	/**
	 * Point of break of contact
	 */
	public TouchPoint upPoint;
	
	/**
	 * Trajectory of wipe represented as chronologically ordered ArrayList of TouchPoints 
	 */
	public Vector<TouchPoint> trajectory = new Vector<TouchPoint>();
	
	/**
	 * State of TouchEvent
	 * TOUCH_STARTED
	 * TOUCH_MOVING
	 * TOUCH_FINISHED
	 */
	public int state = 0;
	
	/**
	 * Sets downPoint
	 */
	public void setDownPoint(TouchPoint downPoint){
		this.downPoint = downPoint;
		trajectory.add(this.downPoint);
	}
	
	/**
	 * Sets upPoint
	 */
	public void setUpPoint(TouchPoint upPoint){
		this.upPoint = upPoint;
		trajectory.add(this.upPoint);
	}
	
	/**
	 * Returns last TouchPoint of trajectory
	 * @return
	 */
	public TouchPoint getLastTouchPoint(){
		return trajectory.get(trajectory.size()-1);
	}
	
	
	/**
	 * Returns second to last TouchPoint of trajectory
	 * @return
	 */
	public TouchPoint getSecondLastTouchPoint(){
		int position=trajectory.size()-2;
		return (position<0)?getLastTouchPoint():trajectory.get(position);
	}
	/**
	 * Computes average side of TouchEvent and allows statements like
	 * "Most of the TouchPoints where on side X of the screen,
	 * although there where some outliers"
	 * @return Average side of TouchEvent
	 * @see TouchPoint
	 */
	public float getAverageSide(){
		float averageSide = 0;
		for(TouchPoint tp : trajectory){
			averageSide += tp.side;
		}
		return averageSide/trajectory.size();
	}
	
	/**
	 * Clears all member variables of TouchEvent
	 */
	public void clear(){
		downPoint = null;
		upPoint = null;
		trajectory.clear();
		state = 0;
	}
	
	/**
	 * Returns duration of TouchEvent until now
	 * @return
	 */
	public float getDuration(){
		return getLastTouchPoint().time-downPoint.time;
	}
	
	/**
	 * Computes velocity of TouchEvent in screenSize per ms
	 * @param wholeTrajectory If true: Velocity over whole trajectory. Else: only between two last Touchpoints
	 * @return
	 */
	public MyVector getVelocity(boolean wholeTrajectory){
		MyVector wipeLength=MyVector.makeVector3(0, 0, 0);
		float duration=1;
		if(wholeTrajectory){
			wipeLength= getLastTouchPoint().screenPosition.subtract(downPoint.screenPosition);
			duration =getDuration();
		}
		else{
			TouchPoint last = getLastTouchPoint();
			TouchPoint secLast=getSecondLastTouchPoint();
			wipeLength=last.screenPosition.subtract(secLast.screenPosition);
			duration=(last.time-secLast.time);
			
		}
//		Log.e("TouchEvent", "length "+wipeLength+" dur "+duration);
		return wipeLength.divide(duration);
	}
	
	/**
	 * Checks if this TouchPoint moved at least {@linkplain com.curluin.inputInterpretation.TouchEvent.minDist}.
	 * @return 
	 */
	public boolean actuallyMoved(){
		float dist=getLastTouchPoint().screenPosition.subtract(getSecondLastTouchPoint().screenPosition).getNorm();
		
		return dist>minDist;
	}
	
	/**
	 * Prints TouchEvent
	 */
	@Override
	public String toString() {
		return "TE[DP=" + downPoint + ",UP=" + upPoint + ",State:"+ state + "]";
	}

	public float getLength() {
		return getLastTouchPoint().screenPosition.subtract(downPoint.screenPosition).getNorm();
	}
	
}
